﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Win32;
using System.Windows;
using System.Xml;
using WinForm = System.Windows.Forms;
using System.IO;

namespace SHomeWorkshop.LunarMind.Commands
{
    /// <summary>
    /// 以此类为模板，制作自定义命令类
    ///     共需要修改１０处！！！
    /// ==============================
    /// 
    /// 粘贴命令。
    /// ★①，修改类名。
    /// </summary>
    public static class PasteCommand
    {
        private static RoutedUICommand routedUICmd;//创建私有字段

        public static RoutedUICommand RoutedUICmd//创建只读静态属性
        {
            get { return routedUICmd; }
        }

        /// <summary>
        /// ★②，修改静态构造方法名。
        /// </summary>
        static PasteCommand()//类型构造器
        {
            //★③，修改两个字符串参数名。★④以及第三个参数的类型名。
            routedUICmd = new RoutedUICommand("PasteCommand", "PasteCommand",
                typeof(PasteCommand),//创建RoutedUICommand对象
                new InputGestureCollection()
                { 
                    //★⑤，修改此处两个参数，以便挂接快捷键。
                    new KeyGesture(Key.V,ModifierKeys.Control,"Ctrl+V")
                });

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        private static CommandBinding cmdBinding = new CommandBinding();

        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //★⑦，修改此方法的实现。

            Paste();
        }

        internal static bool PasteImageData(System.Drawing.Image oImgObj)
        {
            using (MemoryStream stm = new MemoryStream())
            {
                if (oImgObj == null)
                {
                    MessageBox.Show("未能顺利取出剪贴板中的图像数据！"
                        + "请将图片加工一下或另选一张图片。",
                            Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return false;
                }

                // 准备“撤销”与“重做”所需要的数据。
                ModifingItem mi = new ModifingItem()
                {
                    ModifingName = "粘贴图像数据",
                    IsNeedRefreshTitleAndLinesLocation = true
                };

                if (Globals.MainWindow.SelectedTitleImage != null)
                {
                    TitleImage titleImage = Globals.MainWindow.SelectedTitleImage;

                    oImgObj.Save(stm, System.Drawing.Imaging.ImageFormat.Png);//默认以png格式保存
                    if (stm.Length <= 2097152)
                    {
                        byte[] b = stm.GetBuffer();
                        string imgDataText = Convert.ToBase64String(b);

                        System.Xml.XmlNode imgNode = titleImage.XmlData;

                        #region 准备通用的“撤销”与“重做”数据。
                        Action action = new Action(titleImage.ID, -1, titleImage.GetType().Name,
                            "ImageBase64", imgNode.InnerText, imgDataText, ActionType.Property, titleImage.MasterTitle.ID);
                        mi.Add(action);
                        #endregion

                        imgNode.InnerText = imgDataText;
                        titleImage.BuildTitleImage();

                        //加入“撤销”列表。
                        Globals.MainWindow.Do(mi);

                        titleImage.MainImage.Width = oImgObj.Width;
                        titleImage.MainImage.Height = oImgObj.Height;

                        if (titleImage.MainImage.Width > 200 || titleImage.MainImage.Height > 200)
                        {
                            //标题空间太有限了，太大的图像强迫以【图标模式】呈现——除非用户手动更改。
                            //var result = MessageBox.Show("　　粘贴的图像高度或宽度超过了200，需要以【图标模式】呈现吗？", Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Question);
                            //if (result == MessageBoxResult.Yes)
                            //{
                            titleImage.Mode = ImageMode.SmallIcon;
                            //}
                        }

                        Globals.MainWindow.IsModified = true;

                        Globals.MainWindow.RefreshTitleAndLinesLocation();
                        return true;
                    }
                    else
                    {
                        MessageBox.Show("为防止文档体积过分庞大，图片框只支持文件尺寸在 2M 以下的图片！"
                            + "请将图片加工一下或另选一张图片。",
                                Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                        return false;
                    }
                }
                else if (Globals.MainWindow.SelectedPictureBox != null)
                {
                    PictureBox pictureBox = Globals.MainWindow.SelectedPictureBox;

                    oImgObj.Save(stm, System.Drawing.Imaging.ImageFormat.Png);//默认以png格式保存
                    if (stm.Length <= 2097152)
                    {
                        byte[] b = stm.GetBuffer();
                        string imgDataText = Convert.ToBase64String(b);

                        System.Xml.XmlNode imgNode = pictureBox.XmlData;

                        #region 准备通用的“撤销”与“重做”数据。
                        Action action = new Action(pictureBox.ID, -1, pictureBox.GetType().Name,
                            "ImageBase64", imgNode.InnerText, imgDataText);
                        mi.Add(action);
                        #endregion

                        imgNode.InnerText = imgDataText;
                        pictureBox.BuildPictureBox();

                        //加入“撤销”列表。
                        Globals.MainWindow.Do(mi);

                        pictureBox.ImgWidth =
                            pictureBox.MainImage.Width = oImgObj.Width;
                        pictureBox.ImgHeight =
                            pictureBox.MainImage.Height = oImgObj.Height;

                        //这个提示很烦人，不如不加。让用户自己记住去修改好了。
                        //if ((oImgObj.Width > 200 || oImgObj.Height > 200) && pictureBox.Mode != ImageMode.Icon)
                        //{
                        //    MessageBoxResult result= MessageBox.Show("　　图像高度或宽度大于200，要以【图标模式】呈现吗？
                        //}

                        Globals.MainWindow.IsModified = true;

                        return true;
                    }
                    else
                    {
                        MessageBox.Show("为防止文档体积过分庞大，图片框只支持文件尺寸在 2M 以下的图片！"
                            + "请将图片加工一下或另选一张图片。",
                                Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                        return false;
                    }
                }

                return false;
            }
        }

        internal static void InsertAndPasteTitleImage(System.Drawing.Image pastedImgObj)
        {
            if (pastedImgObj == null) return;

            if (Globals.SelectedTitlesList.Count <= 0) return;

            //这种情况，添加到末尾好了。

            Title curTitle = null;

            foreach (Title t in Globals.SelectedTitlesList)
            {
                if (t.IsMainSelectedTitle)
                {
                    curTitle = t;
                    break;
                }
            }

            if (curTitle == null)
            {
                MessageBox.Show("　　发生意外，找不到插入标题图片的基准位置。\r\n" +
                    "　　请重新选取一个标题或标题图片作为插入新标题图片的基准位置！",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            TitleImage ti = new TitleImage(Globals.MainWindow, curTitle);

            XmlNode imgSetNode = curTitle.XmlData.SelectSingleNode("ImageSet");
            if (imgSetNode == null)
            {
                imgSetNode = curTitle.XmlData.AppendXml("<ImageSet/>");
            }

            XmlNode newImgNode = imgSetNode.AppendXml(Properties.Resources.TitleImageOutXml);
            ti.XmlData = newImgNode;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "粘贴标题图像"
            };

            Action actInsertTitleImage = new Action(ti.ID,
                curTitle.ImgStackPanel.Children.Count, ti.GetType().Name, "InsertTitleImage",
                null, ti.XmlData.OuterXml, ActionType.InsertTitleImage, curTitle.ID);

            curTitle.ImgStackPanel.Children.Add(ti);
            mi.Add(actInsertTitleImage);

            ti.IsSelected = true;
            Globals.MainWindow.SelectedTitleImage = ti;

            using (MemoryStream stm = new MemoryStream())
            {
                pastedImgObj.Save(stm, System.Drawing.Imaging.ImageFormat.Png);//默认以png格式保存
                if (stm.Length <= 512000)
                {
                    byte[] b = stm.GetBuffer();
                    string imgDataText = Convert.ToBase64String(b);

                    System.Xml.XmlNode imgNode = ti.XmlData;

                    #region 准备通用的“撤销”与“重做”数据。
                    Action action = new Action(ti.ID, -1, ti.GetType().Name,
                        "ImageBase64", imgNode.InnerText, imgDataText, ActionType.Property, ti.MasterTitle.ID);
                    mi.Add(action);
                    #endregion

                    imgNode.InnerText = imgDataText;
                    ti.BuildTitleImage();

                    ti.MainImage.Width = pastedImgObj.Width;
                    ti.MainImage.Height = pastedImgObj.Height;

                    if (ti.MainImage.Width > 200 || ti.MainImage.Height > 200)
                    {
                        //标题空间太有限了，太大的图像强迫以【图标模式】呈现——除非用户手动更改。
                        //var result = MessageBox.Show("　　粘贴的图像高度或宽度超过了200，需要以【图标模式】呈现吗？", Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Question);
                        //if (result == MessageBoxResult.Yes)
                        //{
                        ti.Mode = ImageMode.SmallIcon;
                        //}
                    }
                }
            }

            mi.OldSelectedTitleID =
            mi.NewSelectedTitleID = curTitle.ID;

            curTitle.Editor.Do(mi);
            curTitle.Editor.IsModified = true;
            curTitle.Editor.RefreshTitleAndLinesLocation();
        }

        internal static void Paste()
        {
            string text = Clipboard.GetText(TextDataFormat.UnicodeText);
            var txt = text.Trim(new char[] { '\r', '\n', '\t', ' ', });

            //先判断是否在已选定的TitleIamge后粘贴另一个TitleImage。
            TitleImage curTitleImage = Globals.MainWindow.SelectedTitleImage;
            if (curTitleImage != null &&
                txt.StartsWith("<LunarMind.TitleImage><Image") && txt.EndsWith("</Image></LunarMind.TitleImage>"))
            {
                PasteTitleImage(curTitleImage, txt);
                return;
            }

            //先粘贴Concept Xaml。

            if (string.IsNullOrEmpty(txt) == false)
            {
                if ((txt.StartsWith("<LunarConcept><Page") && txt.EndsWith("</Page></LunarConcept>")) ||
                    (txt.StartsWith("<Viewbox ") && txt.EndsWith("</Viewbox>")))
                {
                    if (Globals.MainWindow.SelectedPictureBox != null)
                    {
                        PictureBox.PasteContextXamlToPictureBox(txt);
                        return;
                    }
                    else if (Globals.MainWindow.SelectedTitleImage != null)
                    {
                        Globals.MainWindow.SelectedTitleImage.PasteConceptXamlToTitleImage(txt);
                        return;
                    }
                    else if (Globals.MainWindow.MainSelectedTitle != null)
                    {
                        Commands.SetTitleIconXamlTextCommand.PasteXamlTextToTitle(txt);
                        return;
                    }
                }
            }

            #region 先判断要粘贴的是否图像数据块
            WinForm.IDataObject oDataObj = WinForm.Clipboard.GetDataObject();
            if (oDataObj != null)
            {
                if (oDataObj.GetDataPresent(DataFormats.Bitmap))
                {
                    if (Globals.MainWindow.SelectedTitleImage != null ||
                        Globals.MainWindow.SelectedPictureBox != null)
                    {
                        System.Drawing.Image oImgObj = oDataObj.GetData(DataFormats.Bitmap, true) as System.Drawing.Image;
                        PasteImageData(oImgObj);
                        return;
                    }
                    else
                    {
                        if (Globals.MainWindow.SelectedTitleImage == null &&
                            Globals.MainWindow.MainSelectedTitle != null)
                        {
                            System.Drawing.Image oImgObj = oDataObj.GetData(DataFormats.Bitmap, true) as System.Drawing.Image;

                            //如果没有标题图，先自动添加一个。
                            InsertAndPasteTitleImage(oImgObj);
                            //PasteImageData(oImgObj);
                            return;
                        }
                    }
                }
            }
            #endregion

            if (Globals.MainWindow.SelectedTitlesList.Count > 1)
            {
                if (Globals.MainWindow.SelectedTitlesList.Count != 2)
                {
                    MessageBox.Show("在选中多个标题时，不能进行[粘贴]操作！", Globals.AppName,
                        MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                string relationXml = Clipboard.GetText(TextDataFormat.UnicodeText);
                if (relationXml.StartsWith("<LunarMind.Relation>") == false ||
                    relationXml.EndsWith("</LunarMind.Relation>") == false)
                {
                    return;
                }

                PasteRelation(relationXml);
                return;
            }
            else if (Globals.MainWindow.SelectedTitlesList.Count <= 0)
            {
                MessageBox.Show("请先选中【一个】标题作为粘贴的基准位置。", Globals.AppName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            Title curTitle = Globals.SelectedTitlesList[0];

            //MessageBox.Show("剪贴板中无符合要求的格式文本！", Globals.AppName,
            //    MessageBoxButton.OK, MessageBoxImage.Warning);

            //尝试其它情况：
            //①是否正在粘贴一个Comment
            if (text.StartsWith("<LunarMind.Comment>") && text.EndsWith("</LunarMind.Comment>"))
            {
                PasteCommentToTitle(curTitle, text);
                return;
            }

            //②是否正在粘贴一个PictureBox
            if (text.StartsWith("<LunarMind.PictureBox>") && text.EndsWith("</LunarMind.PictureBox>"))
            {
                PastePictureBoxToTitle(curTitle, text);
                return;
            }

            if (text.StartsWith("<LunarMind.TitleImage>") && text.EndsWith("</LunarMind.TitleImage>"))
            {
                PasteTitleImageToTitle(curTitle, text);
                return;
            }

            if (text.StartsWith("<LunarMind.Copy>") == false ||
                text.EndsWith("</LunarMind.Copy>") == false)
            {
                //③是否正在粘贴普通文本
                PasteTextOverrideTitle(curTitle, text);
                return;
            }

            XmlNode titleSet = Globals.MainWindow.MainXmlDocument.DocumentElement.SelectSingleNode("TitleSet");
            if (titleSet == null)
            {
                MessageBox.Show("发生意外错误，未找到文档的后台Xml数据中的TitleSet节点！", Globals.AppName,
                     MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            try
            {
                XmlDocument newDoc = new XmlDocument();
                newDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + text);

                XmlNode titlesNode = newDoc.DocumentElement.SelectSingleNode("Titles");
                XmlNode commentsNode = newDoc.DocumentElement.SelectSingleNode("Comments");
                XmlNode pictureBoxesNode = newDoc.DocumentElement.SelectSingleNode("PictureBoxes");

                XmlNodeList titleNodes = titlesNode.ChildNodes;
                XmlNodeList commentNodes = commentsNode.ChildNodes;
                XmlNodeList pictureBoxNodes = pictureBoxesNode.ChildNodes;

                if (titleNodes == null || titleNodes.Count <= 0) return;

                #region 先解决ＩＤ可能重复的问题。
                if (titleNodes.Count >= 1)
                {
                    for (int i = 0; i < titleNodes.Count; i++)
                    {
                        XmlNode node = titleNodes[i];

                        string newID = Guid.NewGuid().ToString();
                        string oldID = null;

                        XmlAttribute attrCurID = node.GetAttribute("ID");
                        if (attrCurID == null)
                        {
                            node.SetAttribute("ID", newID);
                            continue;
                        }
                        else
                        {
                            oldID = attrCurID.Value;
                        }

                        if (oldID == null || oldID.Length <= 0) continue;

                        for (int i2 = 0; i2 < titleNodes.Count; i2++)
                        {
                            //如果是此标题的下级，则修改为此标题将采用的新ＩＤ
                            if (i == i2) continue;

                            XmlNode anotherNode = titleNodes[i2];
                            XmlAttribute attrHigherID = anotherNode.GetAttribute("HigherLevelTitleID");
                            if (attrHigherID != null && attrHigherID.Value == oldID)
                            {
                                attrHigherID.Value = newID;
                            }
                        }

                        for (int i2 = 0; i2 < commentNodes.Count; i2++)
                        {
                            XmlNode cNode = commentNodes[i2];
                            XmlAttribute attrMasterID = cNode.GetAttribute("MasterTitleID");
                            if (attrMasterID != null && attrMasterID.Value == oldID)
                            {
                                attrMasterID.Value = newID;
                            }

                            cNode.SetAttribute("ID", Guid.NewGuid().ToString());
                        }

                        for (int i2 = 0; i2 < pictureBoxNodes.Count; i2++)
                        {
                            XmlNode pNode = pictureBoxNodes[i2];
                            XmlAttribute attrMasterID = pNode.GetAttribute("MasterTitleID");
                            if (attrMasterID != null && attrMasterID.Value == oldID)
                            {
                                attrMasterID.Value = newID;
                            }

                            pNode.SetAttribute("ID", Guid.NewGuid().ToString());
                        }

                        //最后更改此标题自身的ID.
                        attrCurID.Value = newID;
                    }

                    //对于被剪切（或复制）的首公式们来说，其上级（HigherLevelID）已不存在。要捡出来。
                    for (int i = 0; i < titleNodes.Count; i++)
                    {
                        XmlNode node = titleNodes[i];
                        XmlAttribute attrHigherID = node.GetAttribute("HigherLevelTitleID");
                        if (attrHigherID == null || attrHigherID.Value == "")
                        {
                            MessageBox.Show("剪贴板中的Xml文本数据有问题——可能包括根标题，" +
                                "而根标题是不允许执行[剪切、复制、删除、粘贴]等操作的。",
                                Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                            return;
                        }

                        string myHigherID = attrHigherID.Value;

                        //如果这个HigherLevel没有出现在粘贴板中的其它位置，则说明这个标题是复制时的“顶级标题”。
                        //复制时的顶级标题将成为粘贴时的基准标题的直接下级。

                        int higherCount = 0;
                        for (int i2 = 0; i2 < titleNodes.Count; i2++)
                        {
                            //如果是此标题的下级，则修改为此标题将采用的新ＩＤ
                            if (i == i2) continue;
                            XmlNode anotherNode = titleNodes[i2];
                            XmlAttribute attrID = anotherNode.GetAttribute("ID");
                            if (attrID != null && attrID.Value == myHigherID)
                            {
                                higherCount += 1;
                            }
                        }

                        if (higherCount == 0)
                        {
                            attrHigherID.Value = "TopLevelWhenCopy";
                        }
                    }

                    //检查所有标题中是否存在标题图，如果有，给新ID。
                    for (int i = 0; i < titleNodes.Count; i++)
                    {
                        XmlNode imgSet = titleNodes[i].SelectSingleNode("ImageSet");
                        if (imgSet == null) continue;

                        XmlNodeList childrenImageNodes = imgSet.SelectNodes("Image");
                        if (childrenImageNodes == null || childrenImageNodes.Count <= 0) continue;

                        foreach (XmlNode n in childrenImageNodes)
                        {
                            n.SetAttribute("ID", Guid.NewGuid().ToString());
                        }
                    }
                }
                #endregion

                //此时，存储于临时XmlDoc中的各节点之间仍然保证了引用关系，且不会ＩＤ重复。这样才能粘贴。

                ModifingItem mi = new ModifingItem()
                {
                    IsNeedRefreshTitleAndLinesLocation = true,
                    ModifingName = "粘贴标题"
                };

                Title baseTitle = Globals.MainWindow.SelectedTitlesList[0];

                //总是粘贴为基准标题的下级标题，且如果基准标题已存在下级，则新粘贴的总是在尾部。

                int newTopIndex = baseTitle.GetLowerLevelTitles().Count;

                Title firstPastedTitle = null;

                for (int i = titleNodes.Count - 1; i >= 0; i--)
                {

                    XmlNode newTitleNode = Globals.MainWindow.RootTitle.XmlData.ParentNode.AppendXml(
                         titleNodes[i].OuterXml);
                    Title newTitle = new Title(Globals.MainWindow);
                    newTitle.XmlData = newTitleNode;

                    if (firstPastedTitle == null)
                    {
                        firstPastedTitle = newTitle;
                    }

                    XmlAttribute attrHigherID = newTitleNode.GetAttribute("HigherLevelTitleID");
                    if (attrHigherID == null || attrHigherID.Value == "TopLevelWhenCopy")
                    {
                        newTitle.HigherLevelTitleID = baseTitle.ID;
                        newTitle.Index = newTopIndex;//只有复制或剪切时的“顶级”才需要加索引。
                        newTopIndex++;
                    }

                    Action actInsert = new Action(newTitle.ID, newTopIndex, newTitle.GetType().Name,
                        "InsertTitle", null, newTitle.XmlData.OuterXml, ActionType.InsertTitle,
                        baseTitle.ID);
                    mi.Add(actInsert);
                    Globals.MainWindow.mainCanvas.Children.Add(newTitle);
                }

                XmlNode commentSetNode = Globals.MainWindow.MainXmlDocument.DocumentElement.SelectSingleNode("CommentSet");
                if (commentSetNode == null)
                {
                    commentSetNode = Globals.MainWindow.MainXmlDocument.DocumentElement.AppendXml("<CommentSet />");
                }

                if (commentSetNode != null)
                {
                    for (int i = 0; i < commentNodes.Count; i++)//这个倒不必在意顺序，因为反正所有标题都已经添加完毕了。
                    {
                        XmlNode newCommentNode = commentSetNode.AppendXml(commentNodes[i].OuterXml);

                        XmlAttribute attrMasterID = newCommentNode.GetAttribute("MasterTitleID");
                        if (attrMasterID != null)
                        {
                            Title masterTitle = Globals.MainWindow.GetTitleByID(attrMasterID.Value);
                            if (masterTitle != null)
                            {
                                Comment newComment = new Comment(Globals.MainWindow, masterTitle);
                                newComment.XmlData = newCommentNode;

                                Action actInsertComment = new Action(newComment.ID, -1, newComment.GetType().Name,
                                    "AddComment", null, newComment.XmlData.OuterXml, ActionType.AddComment, newComment.MasterTitleID);

                                Globals.MainWindow.mainCanvas.Children.Add(newComment);
                                Globals.MainWindow.mainCanvas.Children.Add(newComment.ConnectLine);

                                mi.Add(actInsertComment);
                            }
                        }
                    }
                }

                XmlNode pictureBoxSetNode = Globals.MainWindow.MainXmlDocument.DocumentElement.SelectSingleNode("PictureBoxSet");
                if (pictureBoxSetNode == null)
                {
                    pictureBoxSetNode = Globals.MainWindow.MainXmlDocument.DocumentElement.AppendXml("<PictureBoxSet />");
                }

                if (pictureBoxSetNode != null)
                {
                    for (int i = 0; i < pictureBoxNodes.Count; i++)//这个倒不必在意顺序，因为反正所有标题都已经添加完毕了。
                    {
                        XmlNode newPictureBoxNode = pictureBoxSetNode.AppendXml(pictureBoxNodes[i].OuterXml);

                        XmlAttribute attrMasterID = newPictureBoxNode.GetAttribute("MasterTitleID");
                        if (attrMasterID != null)
                        {
                            Title masterTitle = Globals.MainWindow.GetTitleByID(attrMasterID.Value);
                            if (masterTitle != null)
                            {
                                PictureBox newPictureBox = new PictureBox(Globals.MainWindow, masterTitle);
                                newPictureBox.XmlData = newPictureBoxNode;

                                Action actInsertPictureBox = new Action(newPictureBox.ID, -1, newPictureBox.GetType().Name,
                                    "AddPictureBox", null, newPictureBox.XmlData.OuterXml, ActionType.AddPictureBox, newPictureBox.MasterTitleID);

                                Globals.MainWindow.mainCanvas.Children.Add(newPictureBox);
                                Globals.MainWindow.mainCanvas.Children.Add(newPictureBox.ConnectLine);

                                mi.Add(actInsertPictureBox);
                            }
                        }
                    }
                }

                baseTitle.Editor.Do(mi);
                baseTitle.Editor.IsModified = true;
                baseTitle.Editor.RefreshTitleAndLinesLocation();

                if (firstPastedTitle != null)
                {
                    mi.OldSelectedTitleID = curTitle.ID;
                    mi.NewSelectedTitleID = firstPastedTitle.ID;
                    firstPastedTitle.SelectOnlySelf();
                }
            }
            catch (Exception ex)
            {
                Dialogs.LunarMsgBox.MsgBoxShow(Globals.AppName,
                    "在执行“粘贴”操作时发生意外。异常信息如下：\r\n", ex.Message,
                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Error, null,
                    MessageBoxResult.OK, Globals.MainWindow);
                return;
            }
        }

        /// <summary>
        /// 调用本方法前要保证只选中两个标题。
        /// </summary>
        /// <param name="relationXml">含旧信息的Relation的outerXml文本。</param>
        private static void PasteRelation(string relationXml)
        {
            if (relationXml == null ||
                relationXml.Length < "<LunarMind.Relation></LunarMind.Relation>".Length)
            {
                return;
            }

            if (Globals.MainWindow.SelectedTitlesList.Count != 2) return;

            Title endTitle = null;
            Title startTitle = null;

            if (Globals.MainWindow.SelectedTitlesList[0].IsMainSelectedTitle)
            {
                endTitle = Globals.MainWindow.SelectedTitlesList[0];
                startTitle = Globals.MainWindow.SelectedTitlesList[1];
            }
            else
            {
                startTitle = Globals.MainWindow.SelectedTitlesList[0];
                endTitle = Globals.MainWindow.SelectedTitlesList[1];
            }

            if (startTitle == null || endTitle == null)
            {
                MessageBox.Show("试图粘贴关系线时，意外地未能定位首尾锚定标题。", Globals.AppName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            XmlDocument newDoc = new XmlDocument();
            newDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + relationXml);

            XmlNode copyedRelationNode = newDoc.DocumentElement.SelectSingleNode("Relation");
            copyedRelationNode.SetAttribute("ID", Guid.NewGuid().ToString());

            copyedRelationNode.SetAttribute("StartTitleID", startTitle.ID);
            copyedRelationNode.SetAttribute("EndTitleID", endTitle.ID);

            AddRelationCommand.AddRelation(startTitle, endTitle, copyedRelationNode, "粘贴关系线");
        }

        private static void PasteTitleImageToTitle(Title title, string text)
        {
            if (title == null || text.StartsWith("<LunarMind.TitleImage>") == false ||
                text.EndsWith("</LunarMind.TitleImage>") == false)
                return;

            XmlDocument newDoc = new XmlDocument();
            newDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + text);

            XmlNode copyedTitleImageNode = newDoc.DocumentElement.SelectSingleNode("Image");
            copyedTitleImageNode.SetAttribute("ID", Guid.NewGuid().ToString());

            TitleImage ti = new TitleImage(Globals.MainWindow, title);

            XmlNode imgSetNode = title.XmlData.SelectSingleNode("ImageSet");
            if (imgSetNode == null)
            {
                imgSetNode = title.XmlData.AppendXml("<ImageSet/>");
            }

            int index = title.ImgStackPanel.Children.Count;

            XmlNode newImgNode = imgSetNode.AppendXml(copyedTitleImageNode.OuterXml);
            ti.XmlData = newImgNode;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "粘贴标题图像",
                OldSelectedTitleID = title.ID,
                NewSelectedTitleID = title.ID,
            };

            Action actInsertTitleImage = new Action(ti.ID, index,
                ti.GetType().Name, "InsertTitleImage",
                null, ti.XmlData.OuterXml, ActionType.InsertTitleImage, title.ID);

            title.ImgStackPanel.Children.Insert(index, ti);
            mi.Add(actInsertTitleImage);

            title.Editor.Do(mi);
            title.Editor.IsModified = true;
            title.Editor.SelectedTitleImage = ti;
            title.Editor.RefreshTitleAndLinesLocation();

            ti.IsSelected = true;
        }

        /// <summary>
        /// 在当前选定的TitleImage后面粘贴一个新TitleImage。
        /// </summary>
        /// <param name="title"></param>
        /// <param name="text"></param>
        private static void PasteTitleImage(TitleImage selTitleImage, string text)
        {
            if (selTitleImage == null || string.IsNullOrWhiteSpace(text)) return;

            Title title = selTitleImage.MasterTitle;
            if (title == null || text.StartsWith("<LunarMind.TitleImage>") == false ||
                text.EndsWith("</LunarMind.TitleImage>") == false)
                return;

            XmlDocument newDoc = new XmlDocument();
            newDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + text);

            XmlNode copyedTitleImageNode = newDoc.DocumentElement.SelectSingleNode("Image");
            copyedTitleImageNode.SetAttribute("ID", Guid.NewGuid().ToString());

            TitleImage ti = new TitleImage(Globals.MainWindow, title);

            XmlNode imgSetNode = title.XmlData.SelectSingleNode("ImageSet");
            if (imgSetNode == null)
            {
                imgSetNode = title.XmlData.AppendXml("<ImageSet/>");
            }

            int index = title.ImgStackPanel.Children.IndexOf(selTitleImage) + 1;

            XmlNode newImgNode = imgSetNode.InsertXmlAt(copyedTitleImageNode.OuterXml, index);
            ti.XmlData = newImgNode;

            ModifingItem mi = new ModifingItem()
            {
                IsNeedRefreshTitleAndLinesLocation = true,
                ModifingName = "粘贴标题图像",
                OldSelectedTitleID = title.ID,
                NewSelectedTitleID = title.ID,
            };

            Action actInsertTitleImage = new Action(ti.ID, index,
                ti.GetType().Name, "InsertTitleImage",
                null, ti.XmlData.OuterXml, ActionType.InsertTitleImage, title.ID);

            title.ImgStackPanel.Children.Insert(index, ti);
            mi.Add(actInsertTitleImage);

            title.Editor.Do(mi);
            title.Editor.IsModified = true;
            title.Editor.SelectedTitleImage = ti;
            title.Editor.RefreshTitleAndLinesLocation();

            ti.IsSelected = true;
        }

        private static void PasteTextOverrideTitle(Title destTitle, string text)
        {
            if (destTitle == null || destTitle.Editor == null ||
               destTitle.Editor.mainCanvas.Children.Contains(destTitle) == false)
                return;
            if (text == null || text.Length <= 0) return;

            XmlNode destTextSet = destTitle.XmlData.SelectSingleNode("TextSet");

            if (destTextSet == null)
            {
                destTextSet = destTitle.XmlData.AppendXml("<TextSet />");
            }

            if (destTextSet == null)
            {
                MessageBox.Show("发生意外，未能找到标题的<TextSet>节点。无法继续覆盖粘贴文本！",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            //拆分文本
            text = Dialogs.TitleTextEditor.ReplaceXmlChars(text);
            text = text.Replace("\r", "\n");

            string[] txts = text.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < txts.Length; i++)
            {
                string s = txts[i];
                sb.Append("<Text>");
                sb.Append(s);

                if (i < txts.Length - 1)
                {
                    sb.Append("</Text><Text />");
                }
                else
                {
                    sb.Append("</Text>");
                }
            }

            string str = sb.ToString();

            ModifingItem mi = new ModifingItem()
            {
                ModifingName = "覆盖粘贴文本",
                IsNeedRefreshTitleAndLinesLocation = true
            };

            Action actXmlDataInnerXml = new Action(destTitle.ID, -1, destTitle.GetType().Name,
                "XmlDataInnerXml", destTextSet.InnerXml, str);

            destTextSet.InnerXml = str;
            destTitle.BuildTitle();

            mi.Add(actXmlDataInnerXml);

            destTitle.Editor.Do(mi);
            destTitle.Editor.IsModified = true;
            destTitle.Editor.RefreshTitleAndLinesLocation();
        }

        private static void PastePictureBoxToTitle(Title destTitle, string text)
        {
            if (destTitle == null || destTitle.Editor == null ||
                destTitle.Editor.mainCanvas.Children.Contains(destTitle) == false)
                return;
            if (text == null) return;
            if (text.StartsWith("<LunarMind.PictureBox>") == false || text.EndsWith("</LunarMind.PictureBox>") == false) return;

            XmlDocument newDoc = new XmlDocument();
            newDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + text);

            XmlNode pictureBoxNode = newDoc.DocumentElement.SelectSingleNode("PictureBox");
            pictureBoxNode.SetAttribute("ID", Guid.NewGuid().ToString());
            pictureBoxNode.SetAttribute("MasterTitleID", destTitle.ID);

            XmlNode pictureBoxSetNode = destTitle.Editor.MainXmlDocument.DocumentElement.SelectSingleNode("PictureBoxSet");

            XmlNode newNode = pictureBoxSetNode.AppendXml(pictureBoxNode.OuterXml);
            if (newNode == null)
            {
                MessageBox.Show("发生意外，未能添加新PictureBox节点。无法继续粘贴图片框！",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            ModifingItem mi = new ModifingItem() { ModifingName = "粘贴图片框" };

            PictureBox newPictureBox = new PictureBox(destTitle.Editor, destTitle);
            newPictureBox.XmlData = newNode;

            destTitle.Editor.mainCanvas.Children.Add(newPictureBox);
            destTitle.Editor.mainCanvas.Children.Add(newPictureBox.ConnectLine);

            Action act = new Action(newPictureBox.ID, -1, newPictureBox.GetType().Name, "AddPictureBox", null,
                newPictureBox.XmlData.OuterXml, ActionType.AddPictureBox, destTitle.ID);
            mi.Add(act);

            newPictureBox.InvalidateArrange();
            newPictureBox.UpdateLayout();
            newPictureBox.RefreshLoaction();

            destTitle.Editor.SelectedPictureBox = newPictureBox;
            destTitle.Editor.Do(mi);
            destTitle.Editor.IsModified = true;
        }

        private static void PasteCommentToTitle(Title destTitle, string text)
        {
            if (destTitle == null || destTitle.Editor == null ||
                destTitle.Editor.mainCanvas.Children.Contains(destTitle) == false)
                return;
            if (text == null) return;
            if (text.StartsWith("<LunarMind.Comment>") == false || text.EndsWith("</LunarMind.Comment>") == false) return;

            XmlDocument newDoc = new XmlDocument();
            newDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + text);

            XmlNode commentNode = newDoc.DocumentElement.SelectSingleNode("Comment");
            commentNode.SetAttribute("ID", Guid.NewGuid().ToString());
            commentNode.SetAttribute("MasterTitleID", destTitle.ID);

            XmlNode commentSetNode = destTitle.Editor.MainXmlDocument.DocumentElement.SelectSingleNode("CommentSet");

            if (commentSetNode == null)
            {
                commentSetNode = destTitle.Editor.MainXmlDocument.DocumentElement.AppendXml("<CommentSet/>");
            }

            XmlNode newNode = commentSetNode.AppendXml(commentNode.OuterXml);
            if (newNode == null)
            {
                MessageBox.Show("发生意外，未能添加新Comment节点。无法继续粘贴备注文本块！",
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            ModifingItem mi = new ModifingItem() { ModifingName = "粘贴备注文本块" };

            Comment newComment = new Comment(destTitle.Editor, destTitle);
            newComment.XmlData = newNode;

            destTitle.Editor.mainCanvas.Children.Add(newComment);
            destTitle.Editor.mainCanvas.Children.Add(newComment.ConnectLine);

            Action act = new Action(newComment.ID, -1, newComment.GetType().Name, "AddComment", null,
                newComment.XmlData.OuterXml, ActionType.AddComment, destTitle.ID);
            mi.Add(act);

            newComment.InvalidateArrange();
            newComment.UpdateLayout();
            newComment.RefreshLoaction();

            if (newComment.IsSummary)
            {
                mi.IsNeedRefreshTitleAndLinesLocation = true;
                destTitle.Editor.RefreshTitleAndLinesLocation();
            }
            else
            {
                mi.IsNeedRefreshTitleAndLinesLocation = false;
            }

            destTitle.Editor.SelectedComment = newComment;
            destTitle.Editor.Do(mi);
            destTitle.Editor.IsModified = true;
        }

        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //★⑧，修改此方法的实现。
            string text = Clipboard.GetText(TextDataFormat.UnicodeText);

            //    不再限制必须粘贴标题。
            //    text.StartsWith("<LunarMind.Copy>") &&
            //    text.EndsWith("</LunarMind.Copy>")

            if (string.IsNullOrEmpty(text) == false)
            {
                text = text.Trim(new char[] { '\r', '\n', '\t', ' ', });

                if (text.StartsWith("<LunarConcept><Page") && text.EndsWith("</Page></LunarConcept>"))
                {
                    if (Globals.MainWindow.SelectedPictureBox != null ||
                        Globals.MainWindow.SelectedTitleImage != null ||
                        Globals.MainWindow.MainSelectedTitle != null)
                    {
                        e.CanExecute = true;
                        return;
                    }
                }

                if (text.StartsWith("<Viewbox ") && text.EndsWith("</Viewbox>"))
                {
                    if (Globals.MainWindow.SelectedPictureBox != null ||
                        Globals.MainWindow.SelectedTitleImage != null ||
                        Globals.MainWindow.MainSelectedTitle != null)
                    {
                        e.CanExecute = true;
                        return;
                    }
                }

                if (text.StartsWith("<LunarMind.TitleImage><Image") && text.EndsWith("</Image></LunarMind.TitleImage>"))
                {
                    if (Globals.MainWindow.SelectedTitleImage != null ||
                        Globals.MainWindow.MainSelectedTitle != null)
                    {
                        e.CanExecute = true;
                        return;
                    }
                }

                int selectedTitlesCount = Globals.MainWindow.SelectedTitlesList.Count;
                if (selectedTitlesCount == 1)
                {
                    e.CanExecute = true;
                    return;
                }
                else if (selectedTitlesCount == 2)
                {
                    if (text.StartsWith("<LunarMind.Relation>") &&
                        text.EndsWith("</LunarMind.Relation>"))
                    {
                        e.CanExecute = true;
                        return;
                    }
                    else
                    {
                        e.CanExecute = false;
                        return;
                    }
                }
                else
                {
                    e.CanExecute = false;
                    return;
                }
            }
            else
            {
                WinForm.IDataObject oDataObj = WinForm.Clipboard.GetDataObject();
                if (oDataObj != null)
                {
                    if (oDataObj.GetDataPresent(DataFormats.Bitmap) == false)
                    {
                        e.CanExecute = false;
                        return;
                    }
                    else
                    {
                        if (Globals.MainWindow.SelectedTitleImage != null ||
                            Globals.MainWindow.SelectedPictureBox != null)
                        {
                            e.CanExecute = true;
                            return;
                        }
                        else
                        {
                            if (Globals.MainWindow.SelectedTitleImage == null &&
                                Globals.MainWindow.MainSelectedTitle != null)
                            {
                                e.CanExecute = true;
                                return;
                            }
                        }
                    }
                }
            }

            e.CanExecute = false;
        }
    }
}
